import json
from datetime import datetime
import time

from decimal import Decimal

from django import http
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import render
from django.views import View
from django_redis import get_redis_connection

from apps.areas.models import Address
from apps.goods.models import SKU

# 结算页面显示
from apps.orders.models import OrderInfo, OrderGoods
from utils.response_code import RETCODE


class OrderSettlementView(LoginRequiredMixin, View):
    """结算订单"""

    def get(self, request):
        """提供订单结算页面"""
        # 获取登录用户
        user = request.user

        # 1.查询当前用户的收货地址（没有删除的）
        try:
            addresses = Address.objects.filter(user=user, is_deleted=False)

        except:
            #  如果地址为空，渲染模板时会判断，并跳转到地址编辑页面
            addresses = None

        # 2.查询redis数据库－－选中购物车　商品　dict
        redis_client = get_redis_connection('carts')
        carts_data = redis_client.hgetall(user.id)
        # 转换格式
        carts_dict = {}
        for key, value in carts_data.items():
            sku_id = int(key.decode())
            sku_dict = json.loads(value.decode())
            if sku_dict['selected']:
                carts_dict[sku_id] = sku_dict
        # 根据　购物车的数据　sku_ids--SKU
        skus = SKU.objects.filter(id__in=carts_dict.keys())

        # 3.计算金额 +邮费
        total_count = 0
        total_amount = Decimal(0.00)
        for sku in skus:
            # 动态添加个数
            sku.count = carts_dict[sku.id].get('count')
            # 动态添加小计
            sku.amount = sku.count * sku.price
            # 计算总数量和总金额
            total_count += sku.count
            total_amount += sku.count * sku.price

        # 运费
        freight = Decimal('10.00')

        # 4.构建前端显示的数据
        context = {
            'addresses': addresses,
            'skus': skus,
            'total_count': total_count,
            'total_amount': total_amount,
            'freight': freight,
            'payment_amount': total_amount + freight,
            'default_address_id': user.default_address_id
        }
        return render(request, 'place_order.html', context)

# 订单提交
class OrderCommitView(LoginRequiredMixin, View):
    """订单提交"""

    def post(self, request):
        """保存订单信息和订单商品信息"""
        # 获取当前要保存的订单数据（接收参数　json）
        json_dict = json.loads(request.body.decode())
        address_id = json_dict.get('address_id')
        pay_method = json_dict.get('pay_method')
        # 校验参数
        if not all([address_id, pay_method]):
            return http.HttpResponseForbidden('缺少必传参数')
        # 判断address_id是否合法
        try:
            address = Address.objects.get(id=address_id)
        except Exception:
            return http.HttpResponseForbidden('参数address_id错误')
        # 判断pay_method是否合法
        if pay_method not in [OrderInfo.PAY_METHODS_ENUM['CASH'], OrderInfo.PAY_METHODS_ENUM['ALIPAY']]:
            return http.HttpResponseForbidden('参数pay_method错误')
        from django.db import transaction
        with transaction.atomic():
            # 回滚点
            save_point = transaction.savepoint()
            # 获取登录用户
            user = request.user
            # 生成订单编号：年月日时分秒+用户编号
            order_id = datetime.now().strftime('%Y%m%d%H%M%S') + ('%09d' % user.id)
            # 保存订单基本信息 OrderInfo（一）OrderInfo.objects.create()
            try:
                order = OrderInfo.objects.create(
                    order_id=order_id,
                    user=user,
                    address=address,
                    total_count=0,
                    total_amount=Decimal('0'),
                    freight=Decimal('10.00'),
                    pay_method=pay_method,
                    status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'] if pay_method == OrderInfo.PAY_METHODS_ENUM['ALIPAY'] else
                    OrderInfo.ORDER_STATUS_ENUM['UNSEND']
                )
                # 去购物车　redis－选中的商品id 购买个数
                redis_client = get_redis_connection('carts')
                carts_data = redis_client.hgetall(user.id)
                carts_dict = {}
                for key, value in carts_data.items():
                    sku_id = int(key.decode())
                    sku_dict = json.loads(value.decode())
                    if sku_dict['selected']:
                        # 选中
                        carts_dict[sku_id] = sku_dict

                # 循环遍历 商品信息　　sku--计算总金额－总个数
                sku_ids = carts_dict.keys()
                for sku_id in sku_ids:
                    while True:
                        sku = SKU.objects.get(id=sku_id)
                        # 当前购买商品的个数
                        cart_count = carts_dict[sku_id]['count']
                        # 获取老库存　和销量
                        old_stock = sku.stock
                        old_sales = sku.sales

                        # 判断库存是否充足
                        # 回滚事物
                        transaction.savepoint_rollback(save_point)
                        if cart_count > sku.stock:
                            return http.JsonResponse({'code': RETCODE.STOCKERR, 'errmsg': '库存不足'})
                        # 延迟　测试bug
                        time.sleep(10)
                        # 获取购买完毕的库存和销量
                        new_stock = old_stock - cart_count
                        new_sales = old_sales + cart_count
                        # 加乐观锁
                        result = SKU.objects.filter(id=sku_id, stock=old_stock).update(stock=new_stock,sales=new_sales)
                        # 库存充足，sku减少库存, 增加销量
                        # 更新失败如果库存充足　应该继续下单
                        if result == 0:
                            continue

                        # sku.stock -= cart_count
                        # sku.sales += cart_count
                        # sku.save()
                        # spu:sku 1:n增加销量
                        # SPU 增加销量
                        sku.spu.sales += cart_count
                        sku.spu.save()
                        # 保存商品订单中总价和总数量

                        # 计算总个数
                        order.total_count += cart_count
                        # 计算总金额
                        order.total_amount += (cart_count * sku.price)

                        # 生成订单商品信息　OrderGoods.objects.create()
                        OrderGoods.objects.create(
                            order=order,
                            sku=sku,
                            count=cart_count,
                            price=sku.price,
                        )
                        # 下单成功　跳出循环
                        break
                # 总支付金额＋运费 补齐订单表　total_count total_amount save()
                order.total_amount += order.freight
                order.save()
                # 提交事物
                transaction.savepoint_commit(save_point)
                # 清除购物车已经结算过的商品
                redis_client.hdel(user.id, *carts_dict)
            except Exception as e:
                # 事物　暴力回滚
                transaction.savepoint_rollback(save_point)
                return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '下单失败', 'order_id': ""})

            # 返回响应结果
            return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '下单成功', 'order_id': order.order_id})

# 订单提交成功页面
class OrderSuccessView(LoginRequiredMixin, View):
    """提交订单成功"""

    def get(self, request):
        order_id = request.GET.get('order_id')
        payment_amount = request.GET.get('payment_amount')
        pay_method = request.GET.get('pay_method')

        context = {
            'order_id':order_id,
            'payment_amount':payment_amount,
            'pay_method':pay_method
        }
        return render(request, 'order_success.html', context)